package gb

import (
	"encoding/xml"
	"net/http"
	"strings"

	"gitee.com/tonyjia/gb28181/pkg/event"
	"gitee.com/tonyjia/gb28181/pkg/model"
	model2 "gitee.com/tonyjia/gb28181/pkg/model"
	"gitee.com/tonyjia/gb28181/pkg/parser"
	parser2 "gitee.com/tonyjia/gb28181/pkg/parser"
	"github.com/ghettovoice/gosip"
	"github.com/ghettovoice/gosip/sip"
	log "github.com/sirupsen/logrus"
)

var (
	subscribeHandler = map[string]gosip.RequestHandler{
		// 订阅设备目录信息
		"Query:Catalog":   catalogSubscribeHandler,
		"Query:Keepalive": keepaliveSubscribeHandler,
	}
)

func SubscribeHandler(req sip.Request, tx sip.ServerTransaction) {
	log.Debugf("Subscribe事件消息体：\n%s", req)
	if l, ok := req.ContentLength(); !ok || l.Equals(0) {
		log.Debug("该Subscribe消息的消息体长度为0，返回OK")
		_ = tx.Respond(sip.NewResponseFromRequest("", req, http.StatusOK, http.StatusText(http.StatusOK), ""))
	}
	body := req.Body()
	cmdType, err := parser.GetCmdTypeFromXML(body)
	log.Debug("解析出的命令：", cmdType)
	if err != nil {
		return
	}
	handler, ok := subscribeHandler[cmdType]
	if !ok {
		log.Warn("不支持的Subscribe方法实现")
		return
	}
	handler(req, tx)
}

func catalogSubscribeHandler(req sip.Request, tx sip.ServerTransaction) {
	defer func() {
		_ = responseAck(tx, req)
	}()

	catalog := model2.DeviceCatalogRequest{}

	decoder := xml.NewDecoder(strings.NewReader(req.Body()))
	decoder.CharsetReader = gb2312CharsetReader
	err := decoder.Decode(&catalog)

	if err != nil {
		// maybe charset is GBK, so take request body convert utf8
		b, err := gbkToUtf8([]byte(req.Body()))

		if err != nil {
			log.Error(err)
			return
		}
		err = xml.Unmarshal(b, &catalog)
		if err != nil {
			log.Error(err)
			return
		}
	}

	eventBus := event.GetEventBus()
	eventBus.Subscribe(event.Catalog, catalog.DeviceID.DeviceID)
}

func keepaliveSubscribeHandler(req sip.Request, tx sip.ServerTransaction) {
	keepalive := &model.Keepalive{}

	decoder := xml.NewDecoder(strings.NewReader(req.Body()))
	decoder.CharsetReader = gb2312CharsetReader
	err := decoder.Decode(&keepalive)

	if err != nil {
		// maybe charset is GBK, so take request body convert utf8
		b, err := gbkToUtf8([]byte(req.Body()))

		if err != nil {
			log.Error(err)
			return
		}
		err = xml.Unmarshal(b, &keepalive)
		if err != nil {
			log.Error(err)
			return
		}
	}

	device, ok := parser2.DeviceFromRequest(req)
	if !ok {
		return
	}
	//获取到设备信息回调
	log.Infof("设备信息为：%+v", device)
	_ = tx.Respond(sip.NewResponseFromRequest("", req, http.StatusOK, http.StatusText(http.StatusOK), ""))

	eventBus := event.GetEventBus()
	eventBus.Subscribe(event.Keepalive, keepalive.DeviceID)
}
